#import "BWStitch.h"
#import "BWJunkyard.h"


// --------------------------------------------------
// notification stuff

NSString *BWStitch_StitchChangedNotification
    = @"BWStitch stitch changed notification";


// --------------------------------------------------
// attribute dictionary keys

static NSString *BWStitch_StartSquareKey = @"start square";
static NSString *BWStitch_StartPartKey = @"start part";

static NSString *BWStitch_EndSquareKey = @"end square";
static NSString *BWStitch_EndPartKey = @"end part";

static NSString *BWStitch_FillColorKey = @"fill color";
static NSString *BWStitch_StrokeColorKey = @"stroke color";

static NSString *BWStitch_BendFactorKey = @"bend factor";
static NSString *BWStitch_BendDisplacementKey = @"bend displacement";
static NSString *BWStitch_BendFlatnessKey = @"bend flatness";

static NSString *BWStitch_WidthKey = @"width";

static NSString *BWStitch_ArrowKey = @"arrow";
static NSString *BWStitch_ArrowWeightKey = @"arrow weight";
static NSString *BWStitch_ArrowLengthKey = @"arrow length";
static NSString *BWStitch_ArrowColorKey = @"arrow color";

static NSString *BWStitch_StartLabelVisibility = @"start label visibility";
static NSString *BWStitch_EndLabelVisibility = @"end label visibility";

static NSString *BWStitch_StartLabelInsideStitch = @"start label inside";
static NSString *BWStitch_EndLabelInsideStitch = @"end label inside";

static NSString *BWStitch_CustomStartLabel = @"custom start label";
static NSString *BWStitch_CustomEndLabel = @"custom end label";

static NSString *BWStitch_StartLabelDisplacement = @"start label";
static NSString *BWStitch_EndLabelDisplacement = @"end label";

static NSString *BWStitch_StartLabelDisplacementAngle = @"start label angle";
static NSString *BWStitch_EndLabelDisplacementAngle = @"end label angle";

static NSString *BWStitch_DisplayDebugControlPoints 
    = @"display debug control points";

@interface BWStitch(privateMethods)

- (void) setFloat: (float) value  
           forKey: (NSString *) key;
- (float) floatForKey: (NSString *) key  
              default: (float) defaulValue;

- (void) setBool: (BOOL) value  
          forKey: (NSString *) key;
- (BOOL) boolForKey: (NSString *) key  
            default: (BOOL) defaulValue;

- (void) setColor: (NSColor *) color
           forKey: (NSString *) key;
- (NSColor *) colorForKey: (NSString *) key
                  default: (NSColor *) defaulColor;

@end // BWStitch privateMethods


@implementation BWStitch

- (void) commonInit
{
        transientWidth = BWStitch_NO_TRANSIENT_VALUE;
        transientBendFactor = BWStitch_NO_TRANSIENT_VALUE;
        transientBendDisplacement = BWStitch_NO_TRANSIENT_VALUE;
        transientBendFlatness = BWStitch_NO_TRANSIENT_VALUE;
        transientArrowLength = BWStitch_NO_TRANSIENT_VALUE;
        transientArrowWeight = BWStitch_NO_TRANSIENT_VALUE;
        transientStartLabelDisplacement = BWStitch_NO_TRANSIENT_VALUE;
        transientEndLabelDisplacement = BWStitch_NO_TRANSIENT_VALUE;
        transientStartLabelDisplacementAngle = BWStitch_NO_TRANSIENT_VALUE;
        transientEndLabelDisplacementAngle = BWStitch_NO_TRANSIENT_VALUE;

        transientStartSquarePart = BWGrid_InvalidSquare;
        transientEndSquarePart = BWGrid_InvalidSquare;

} // commonInit



- (id) init
{
    if (self = [super init]) {
        attributes = [[NSMutableDictionary alloc] init];

        [self commonInit];
    }

    return (self);

} // init


- (id) copyWithZone: (NSZone *) zone
{
    BWStitch *copy;
    copy = [[[self class] allocWithZone: zone] init];

    copy->attributes = [attributes mutableCopyWithZone: zone];

    return (copy);
    
} // copyWithZone


- (void) encodeWithCoder: (NSCoder *) coder
{
    [coder encodeObject: attributes];

} // encodeWithCoder


- (id) initWithCoder: (NSCoder *) coder
{
    
    if (self = [super init]) {
        [self commonInit];
        attributes = [coder decodeObject];
        [attributes retain];
    }
    
    return (self);

} // initWithCoder


- (void) dealloc
{
    [attributes release];
    [transientFillColor release];
    [transientArrowColor release];

    [super dealloc];

} // dealloc



- (void) postStitchChangeNotification
{
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    [center postNotificationName: BWStitch_StitchChangedNotification
            object: self
            userInfo: nil];

} // postStitchChangeNotification



- (void) setStartSquare: (BWGrid_Square) square
                   part: (BWGrid_SquarePart) part
{
    NSValue *squareValue;
    squareValue = [[NSValue alloc] initWithBytes: &square
                                   objCType: @encode(BWGrid_Square)];
    NSValue *partValue;
    partValue = [[NSValue alloc] initWithBytes: &part
                                 objCType: @encode(BWGrid_SquarePart)];

    [attributes setObject: squareValue
                forKey: BWStitch_StartSquareKey];
    [attributes setObject: partValue
                forKey: BWStitch_StartPartKey];

    [squareValue release];
    [partValue release];

    [self postStitchChangeNotification];
    
} // setStartSquare


- (void) getStartSquare: (BWGrid_Square *) square
                   part: (BWGrid_SquarePart *) part
{
    if (transientStartSquarePart == BWGrid_InvalidSquare) {
        NSValue *value;
        
        value = [attributes objectForKey: BWStitch_StartSquareKey];
        [value getValue: square];
        
        if (part != NULL) {
            value = [attributes objectForKey: BWStitch_StartPartKey];
            [value getValue: part];
        }

    } else {
        [self getTransientStartSquare: square  part: part];
    }
        
} // getStartSquare


- (BWGrid_SquarePart) getStartPart
{
    BWGrid_SquarePart part;

    if (transientStartSquarePart == BWGrid_InvalidSquare) {
        NSValue *value;
        value = [attributes objectForKey: BWStitch_StartPartKey];
        
        [value getValue: &part];

    } else {
        part = transientStartSquarePart;
    }
        
    return (part);

} // getStartPart


- (void) setTransientStartSquare: (BWGrid_Square) square
                            part: (BWGrid_SquarePart) part
{
    transientStartSquare = square;
    transientStartSquarePart = part;

    [self postStitchChangeNotification];
    
} // setTransientStartSquare


- (void) getTransientStartSquare: (BWGrid_Square *) square
                            part: (BWGrid_SquarePart *) part
{
    if (square != NULL) {
        *square = transientStartSquare;
    }
    if (part != NULL) {
        *part = transientStartSquarePart;
    }

} // getTransientStartSquare




- (void) setEndSquare: (BWGrid_Square) square
                 part: (BWGrid_SquarePart) part
{
    NSValue *squareValue;
    squareValue = [[NSValue alloc] initWithBytes: &square
                                   objCType: @encode(BWGrid_Square)];
    NSValue *partValue;
    partValue = [[NSValue alloc] initWithBytes: &part
                                 objCType: @encode(BWGrid_SquarePart)];

    [attributes setObject: squareValue
                forKey: BWStitch_EndSquareKey];
    [attributes setObject: partValue
                forKey: BWStitch_EndPartKey];

    [squareValue release];
    [partValue release];
    
    [self postStitchChangeNotification];
    
} // setEndSquare


- (void) getEndSquare: (BWGrid_Square *) square
                 part: (BWGrid_SquarePart *) part
{
    if (transientEndSquarePart == BWGrid_InvalidSquare) {
        NSValue *value;

        value = [attributes objectForKey: BWStitch_EndSquareKey];
        [value getValue: square];
        
        if (part != NULL) {
            value = [attributes objectForKey: BWStitch_EndPartKey];
            [value getValue: part];
        }
    } else {
        [self getTransientEndSquare: square  part: part];
    }

} // getEndSquare


- (BWGrid_SquarePart) getEndPart
{
    NSValue *value;
    value = [attributes objectForKey: BWStitch_EndPartKey];
    
    BWGrid_SquarePart part;
    [value getValue: &part];

    return (part);

} // getEndPart



- (void) setTransientEndSquare: (BWGrid_Square) square
                            part: (BWGrid_SquarePart) part
{
    transientEndSquare = square;
    transientEndSquarePart = part;

    [self postStitchChangeNotification];
    
} // setTransientEndSquare


- (void) getTransientEndSquare: (BWGrid_Square *) square
                            part: (BWGrid_SquarePart *) part
{
    if (square != NULL) {
        *square = transientEndSquare;
    }
    if (part != NULL) {
        *part = transientEndSquarePart;
    }
} // getTransientEndSquare



- (void) flip
{
    BWGrid_Square startSquare, endSquare;
    BWGrid_SquarePart startPart, endPart;

    [self getStartSquare: &startSquare  part: &startPart];
    [self getEndSquare: &endSquare  part: &endPart];

    [self setStartSquare: endSquare  part: endPart];
    [self setEndSquare: startSquare  part: startPart];

} // flip



- (void) setFillColor: (NSColor *) color
{
    [self setColor: color
          forKey: BWStitch_FillColorKey];

    [self postStitchChangeNotification];
    
} // setFillColor


- (NSColor *) fillColor
{
    NSColor *fillColor;
    if (transientFillColor == NULL) {
        fillColor = [self colorForKey: BWStitch_FillColorKey
                          default: [NSColor whiteColor]];
    } else {
        fillColor = transientFillColor;
    }

    return (fillColor);

} // fillColor


- (void) setTransientFillColor: (NSColor *) color
{
    [transientFillColor release];
    transientFillColor = [color copy];

    [self postStitchChangeNotification];
    
} // setTransientFillColor


- (NSColor *) transientFillColor
{
    return (transientFillColor);

} // transientFillColor


- (void) setStrokeColor: (NSColor *) color
{
    [self setColor: color
          forKey: BWStitch_StrokeColorKey];

    [self postStitchChangeNotification];
    
} // setStrokeColor


- (NSColor *) strokeColor
{
    NSColor *strokeColor;
    strokeColor = [self colorForKey: BWStitch_StrokeColorKey
                      default: [NSColor blackColor]];

    return (strokeColor);

} // strokeColor


- (void) setWidth: (float) width
{
    [self setFloat: width
          forKey: BWStitch_WidthKey];

    [self postStitchChangeNotification];
    
} // setWidth


- (float) width
{
    float width;

    if (isNaN(transientWidth)) {
        width = [self floatForKey: BWStitch_WidthKey
                      default: 4.0];
    } else {
        width = transientWidth;
    }

    return (width);

} // width


- (void) setTransientWidth: (float) newWidth
{
    transientWidth = newWidth;

    [self postStitchChangeNotification];
    
} // setTransientWidth


- (float) transientWidth
{
    return (transientWidth);

} // transientWidth


- (void) setArrow: (BWStitch_ArrowKind) arrow
{
    NSValue *value;
    value = [[NSValue alloc] initWithBytes: &arrow
                             objCType: @encode(BWStitch_ArrowKind)];

    [attributes setObject: value
                forKey: BWStitch_ArrowKey];
    [value release];
    
    [self postStitchChangeNotification];
    
} // setArrow


- (BWStitch_ArrowKind) arrow
{
    BWStitch_ArrowKind arrow;
    arrow = BWStitch_NoArrow;

    NSValue *value;
    value = [attributes objectForKey: BWStitch_ArrowKey];

    if (value != nil) {
        [value getValue: &arrow];
    }

    return (arrow);

} // arrow


- (void) setArrowLength: (float) arrowLength
{
    [self setFloat: arrowLength
          forKey: BWStitch_ArrowLengthKey];

    [self postStitchChangeNotification];
    
} // setArrowLength


- (float) arrowLength
{
    float arrowLength;

    if (isNaN (transientArrowLength)) {
        arrowLength = [self floatForKey: BWStitch_ArrowLengthKey
                            default: 35.0];
    } else {
        return (transientArrowLength);
    }

    return (arrowLength);

} // arrowLength



- (void) setTransientArrowLength: (float) arrowLength
{
    transientArrowLength = arrowLength;

    [self postStitchChangeNotification];
    
} // setTransientArrowLength


- (float) transientArrowLength
{
    return (transientArrowLength);

} // transientArrowLength



- (void) setArrowWeight: (float) arrowWeight
{
    [self setFloat: arrowWeight
          forKey: BWStitch_ArrowWeightKey];

    [self postStitchChangeNotification];
    
} // setArrowWeight


- (float) arrowWeight
{
    float arrowWeight;
    if (isNaN(transientArrowWeight)) {
        arrowWeight = [self floatForKey: BWStitch_ArrowWeightKey
                            default: 3.0];
    } else {
        arrowWeight = transientArrowWeight;
    }

    return (arrowWeight);

} // arrowWeight



- (void) setTransientArrowWeight: (float) arrowWeight
{
    transientArrowWeight = arrowWeight;

    [self postStitchChangeNotification];
    
} // setTransientArrowWeight


- (float) transientArrowWeight
{
    return (transientArrowWeight);

} // transientArrowWeight


- (void) setArrowColor: (NSColor *) color
{
    [self setColor: color
          forKey: BWStitch_ArrowColorKey];

    [self postStitchChangeNotification];
    
} // setArrowColor


- (NSColor *) arrowColor
{
    NSColor *arrowColor;

    if (transientArrowColor == NULL) {
        arrowColor = [self colorForKey: BWStitch_ArrowColorKey
                           default: [NSColor blackColor]];
    } else {
        arrowColor = transientArrowColor;
    }

    return (arrowColor);

} // arrowColor


- (void) setTransientArrowColor: (NSColor *) color
{
    [transientArrowColor release];
    transientArrowColor = [color copy];

    [self postStitchChangeNotification];
    
} // setTransientArrowColor


- (NSColor *) transientArrowColor
{
    return (transientArrowColor);

} // transientArrowColor


- (void) setBendFactor: (float) bendFactor
{
    [self setFloat: bendFactor
          forKey: BWStitch_BendFactorKey];

    [self postStitchChangeNotification];
    
} // setBendFactor


- (float) bendFactor
{
    float bendFactor;

    if (isNaN(transientBendFactor)) {
        bendFactor = [self floatForKey: BWStitch_BendFactorKey
                           default: 0.0];
    } else {
        bendFactor = transientBendFactor;
    }

    return (bendFactor);

} // bendFactor


- (void) setTransientBendFactor: (float) bendFactor
{
    transientBendFactor = bendFactor;

    [self postStitchChangeNotification];
    
} // setBendFactor


- (float) transientBendFactor
{
    return (transientBendFactor);

} // transientBendFactor


- (void) setBendDisplacement: (float) bendDisplacement
{
    [self setFloat: bendDisplacement
          forKey: BWStitch_BendDisplacementKey];

    [self postStitchChangeNotification];
    
} // setBendDisplacement


- (float) bendDisplacement
{
    float bendDisplacement;
    if (isNaN(transientBendDisplacement)) {
        bendDisplacement = [self floatForKey: BWStitch_BendDisplacementKey
                                 default: 0.0];
    } else {
        bendDisplacement = transientBendDisplacement;
    }
    
    return (bendDisplacement);

} // bendDisplacement



- (void) setTransientBendDisplacement: (float) bendDisplacement
{
    transientBendDisplacement = bendDisplacement;

    [self postStitchChangeNotification];
    
} // setBendDisplacement


- (float) transientBendDisplacement
{
    return (transientBendDisplacement);

} // transientBendDisplacement


- (void) setBendFlatness: (float) bendFlatness
{
    [self setFloat: bendFlatness
          forKey: BWStitch_BendFlatnessKey];

    [self postStitchChangeNotification];
    
} // setBendFlatness


- (float) bendFlatness
{
    float bendFlatness;

    if (isNaN(transientBendFlatness)) {
        bendFlatness = [self floatForKey: BWStitch_BendFlatnessKey
                             default: 0.0];
    } else {
        bendFlatness = transientBendFlatness;
    }

    return (bendFlatness);

} // bendFlatness



- (void) setTransientBendFlatness: (float) bendFlatness
{
    transientBendFlatness = bendFlatness;

    [self postStitchChangeNotification];
    
} // setTransientBendFlatness


- (float) transientBendFlatness
{
    return (transientBendFlatness);

} // transientBendFlatness



- (void) setDisplayDebugControlPoints: (BOOL) onOff
{
    NSNumber *number;
    number = [NSNumber numberWithBool: onOff];

    [attributes setObject: number
                forKey: BWStitch_DisplayDebugControlPoints];

    [self postStitchChangeNotification];
    
} // setDisplayDebugControlPoints


- (BOOL) displayDebugControlPoints
{
    NSNumber *number;
    number = [attributes objectForKey: BWStitch_DisplayDebugControlPoints];

    BOOL onOff = NO;

    if (number != nil) {
        onOff = [number boolValue];
    }

    return (onOff);
    
} // displayDebugControlPoints



- (void) setFloat: (float) value  forKey: (NSString *) key
{
    NSNumber *number;
    number = [NSNumber numberWithFloat: value];

    [attributes setObject: number
                forKey: key];

    [self postStitchChangeNotification];
   

} // setFloat


- (float) floatForKey: (NSString *) key   default: (float) defaultValue
{
    NSNumber *number;
    number = [attributes objectForKey: key];

    float value;

    if (number == nil) {
        value = defaultValue;
    } else {
        value = [number floatValue];
    }

    return (value);

} // floatForKey


- (void) setBool: (BOOL) value  forKey: (NSString *) key
{
    NSNumber *number;
    number = [NSNumber numberWithBool: value];

    [attributes setObject: number
                forKey: key];

    [self postStitchChangeNotification];
    
} // setBool


- (BOOL) boolForKey: (NSString *) key   default: (BOOL) defaultValue
{
    NSNumber *number;
    number = [attributes objectForKey: key];

    bool value;

    if (number == nil) {
        value = defaultValue;
    } else {
        value = [number boolValue];
    }

    return (value);

} // boolForKey


- (void) setColor: (NSColor *) color
           forKey: (NSString *) key
{
    if (color == nil) {
        [attributes removeObjectForKey: key];
    } else {
        [attributes setObject: color
                    forKey: key];
    }
    
    [self postStitchChangeNotification];
    
} // setColor


- (NSColor *) colorForKey: (NSString *) key  
                  default: (NSColor *) defaultColor
{
    NSColor *color;
    color = [attributes objectForKey: key];

    if (color == nil) {
        color = defaultColor;
    }

    return (color);

} // colorForKey


- (void) setStartLabelVisibility: (BOOL) onOff
{
    [self setBool: onOff
          forKey: BWStitch_StartLabelVisibility];

} // setStartLabelVisibility


- (BOOL) startLabelVisibility
{
    BOOL onOff;
    onOff = [self boolForKey: BWStitch_StartLabelVisibility
                  default: YES];

    return (onOff);

} // startLabelVisibility


- (void) setEndLabelVisibility: (BOOL) onOff
{
    [self setBool: onOff
          forKey: BWStitch_EndLabelVisibility];

} // setEndLabelVisibility


- (BOOL) endLabelVisibility
{
    BOOL onOff;
    onOff = [self boolForKey: BWStitch_EndLabelVisibility
                  default: YES];

    return (onOff);

} // endLabelVisibility


- (void) setStartLabelInsideStitch: (BOOL) onOff
{
    [self setBool: onOff
          forKey: BWStitch_StartLabelInsideStitch];

} // setStartLabelInsideStitch


- (BOOL) startLabelInsideStitch
{
    BOOL onOff;
    onOff = [self boolForKey: BWStitch_StartLabelInsideStitch
                  default: NO];

    return (onOff);

} // startLabelInsideStitch



- (void) setEndLabelInsideStitch: (BOOL) onOff
{
    [self setBool: onOff
          forKey: BWStitch_EndLabelInsideStitch];

} // setEndLabelInsideStitch


- (BOOL) endLabelInsideStitch
{
    BOOL onOff;
    onOff = [self boolForKey: BWStitch_EndLabelInsideStitch
                  default: NO];

    return (onOff);

} // endLabelInsideStitch




- (void) setCustomStartLabel: (NSString *) label
{
    if (label == nil) {
        [attributes removeObjectForKey: BWStitch_CustomStartLabel];
    } else {
        [attributes setObject: [[label copy] autorelease]
                    forKey: BWStitch_CustomStartLabel];
    }

} // setCustomStartLabel


- (NSString*) customStartLabel
{
    NSString *label;
    label = [attributes objectForKey: BWStitch_CustomStartLabel];

    return (label);

} // customStartLabel


- (void) setCustomEndLabel: (NSString *) label
{
    if (label == nil) {
        [attributes removeObjectForKey: BWStitch_CustomEndLabel];
    } else {
        [attributes setObject: [[label copy] autorelease]
                    forKey: BWStitch_CustomEndLabel];
    }

} // setCustomEndLabel


- (NSString*) customEndLabel
{
    NSString *label;
    label = [attributes objectForKey: BWStitch_CustomEndLabel];

    return (label);

} // customEndLabel



- (void) setStartLabelDisplacement: (float) displacement
{
    [self setFloat: displacement
          forKey: BWStitch_StartLabelDisplacement];
} // setStartLabelDisplacement


- (float) startLabelDisplacement
{
    float displacement;

    if (isNaN(transientStartLabelDisplacement)) {
        displacement
            = [self floatForKey: BWStitch_StartLabelDisplacement
                    default: 0.0];
    } else {
        displacement = transientStartLabelDisplacement;
    }
    
    return (displacement);

} // startLabelDisplacement


- (void) setTransientStartLabelDisplacement: (float) displacement
{
    transientStartLabelDisplacement = displacement;
} // setTransientStartLabelDisplacement


- (float) transientStartLabelDisplacement
{
    return (transientStartLabelDisplacement);

} // transientStartLabelDisplacement


- (void) setEndLabelDisplacement: (float) displacement
{
    [self setFloat: displacement
          forKey: BWStitch_EndLabelDisplacement];
} // setEndLabelDisplacement


- (float) endLabelDisplacement
{
    float displacement;

    if (isNaN(transientEndLabelDisplacement)) {
        displacement
            = [self floatForKey: BWStitch_EndLabelDisplacement
                    default: 0.0];
    } else {
        displacement = transientEndLabelDisplacement;
    }
    
    return (displacement);

} // endLabelDisplacement



- (void) setTransientEndLabelDisplacement: (float) displacement
{
    transientEndLabelDisplacement = displacement;
} // setTransientEndLabelDisplacement


- (float) transientEndLabelDisplacement
{
    return (transientEndLabelDisplacement);

} // transientEndLabelDisplacement



- (void) setStartLabelDisplacementAngle: (float) angleInDegrees
{
    [self setFloat: angleInDegrees
          forKey: BWStitch_StartLabelDisplacementAngle];

} // setStartLabelDisplacementAngle


- (float) startLabelDisplacementAngle
{
    float displacementAngle;

    if (isNaN(transientStartLabelDisplacementAngle)) {
        displacementAngle 
            = [self floatForKey: BWStitch_StartLabelDisplacementAngle
                    default: 0.0];
    } else {
        displacementAngle = transientStartLabelDisplacementAngle;
    }
    
    return (displacementAngle);

} // startLabelDisplacementAngle


- (void) setTransientStartLabelDisplacementAngle: (float) angleInDegrees
{
    transientStartLabelDisplacementAngle = angleInDegrees;

} // setTransientStartLabelDisplacementAngle


- (float) transientStartLabelDisplacementAngle
{
    return (transientStartLabelDisplacementAngle);

} // transientStartLabelDisplacementAngle


- (void) setEndLabelDisplacementAngle: (float) angleInDegrees
{
    [self setFloat: angleInDegrees
          forKey: BWStitch_EndLabelDisplacementAngle];

} // setEndLabelDisplacementAngle


- (float) endLabelDisplacementAngle
{
    float displacementAngle;
    if (isNaN(transientEndLabelDisplacementAngle)) {
        displacementAngle 
            = [self floatForKey: BWStitch_EndLabelDisplacementAngle
                    default: 0.0];
    } else {
        displacementAngle = transientEndLabelDisplacementAngle;
    }
    
    return (displacementAngle);

} // endLabelDisplacementAngle


- (void) setTransientEndLabelDisplacementAngle: (float) angleInDegrees
{
    transientEndLabelDisplacementAngle = angleInDegrees;

} // setTransientEndLabelDisplacementAngle


- (float) transientEndLabelDisplacementAngle
{
    return (transientEndLabelDisplacementAngle);

} // transientEndLabelDisplacementAngle



- (NSString *) description
{
    NSMutableString *string = [[NSMutableString alloc] init];

    BWGrid_Square square;
    BWGrid_SquarePart part;

    [string appendString: @"\n"];

    [self getStartSquare: &square  part: &part];
    [string appendFormat: @"start square: (%d %d)  part: %d\n",
            square.x, square.y, part];

    [self getEndSquare: &square  part: &part];
    [string appendFormat: @"end square: (%d %d)  part: %d\n",
            square.x, square.y, part];

    [string appendFormat: @"width: %f", [self width]];

    [string autorelease];

    return (string);

} // description


@end // BWStitch



